Java通过锁的顺序避免死锁

内容:通过获取锁的顺序来避免死锁。例如:银行账户转账问题,两个用户转账的话,如果采用一般的synchronized嵌套的话,容易造成死锁,现在我们通过类似哲学家问题的解决方案一样:先获取同一个锁,才有资格获取下一个。而判断是通过System.identityHashCode()来生成类的hashcode()的返回值作为唯一标识,相同的话,我们再加一把锁。

class Account {
	private int money;
	
	public Account(int money) {
		this.money = money;
	}
	
	public void debit(int amount) {
		System.out.println("after debit " + amount + " " + this.money + " -> " + (this.money-amount));
		this.money -= amount;
	}
	
	public void credit(int amount) {
		System.out.println("after credit " + amount + " " + this.money + " -> " + (this.money+amount));
		this.money += amount;
	}
	
	public int get() {
		return this.money;
	}
}

public class OrderLock {
	private static final Object tieLock = new Object();
	
	public void transferMoney(final Account fromAcct, final Account toAcct, final int amount) 
			throws InsufficientResourcesException {
		class Helper {
			public void transfer() throws InsufficientResourcesException {
				if (fromAcct.get() < amount) 
					throw new InsufficientResourcesException();
				else {
					fromAcct.debit(amount);
					toAcct.credit(amount);
				}
			}
		}
		
		int fromHash = System.identityHashCode(fromAcct);
		int toHash = System.identityHashCode(toAcct);
		
		if (fromHash < toHash) {
			synchronized (fromAcct) {
				synchronized (toAcct) {
					new Helper().transfer();
				}
			}
		} else if (fromHash > toHash) {
			synchronized (toAcct) {
				synchronized (fromAcct) {
					new Helper().transfer();
				}
				
			}
		} else {
			synchronized (tieLock) {
				synchronized (fromAcct) {
					synchronized (toAcct) {
						new Helper().transfer();
					}
				}
			}
		}
	}
	
	class MyThread implements Runnable {
		private Account fromAcct;
		private Account toAcct;
		private int amount;
		
		public MyThread(Account fromAcct, Account toAcct, int amount) {
			this.fromAcct = fromAcct;
			this.toAcct = toAcct;
			this.amount = amount;
		}


		@Override
		public void run() {
			try {
				transferMoney(this.fromAcct, this.toAcct, this.amount);
			} catch (InsufficientResourcesException e) {
				System.out.println("操作失败");
			}
		}
		
	}
	
	public static void main(String[] args) {
		Account fromAcct = new Account(100);
		Account toAcct = new Account(230);
		OrderLock orderLock = new OrderLock();
		ExecutorService threadPool = Executors.newCachedThreadPool();
		for (int i = 0; i < 5; i++) {
			if ((i & 1) == 0)
				threadPool.execute(orderLock.new MyThread(fromAcct, toAcct, 10));
			else threadPool.execute(orderLock.new MyThread(toAcct, fromAcct, 10));
		}
	}
}


  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值